﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.Collections;
using System.Collections.ObjectModel;
using System.Reflection;

namespace KylinORM.Utils
{
    /// <summary>
    /// 表示键或索引可访问的键/值对的只读集合。
    /// </summary>
    public class ReadonlyOrderedDictionary<T> : ReadOnlyCollection<KeyValuePair<string, T>>,ICloneable<ReadonlyOrderedDictionary<T>>
    {
        internal ReadonlyOrderedDictionary(IList<KeyValuePair<string, T>> list)
            : base(list)
        {
            int count = this.Items.Count;
            this.keys = new string[count];
            this.values = new T[count];
            //初始化键值对
            for (int i = 0; i < count; i++)
            {
                KeyValuePair<string, T> kv = this.Items[i];
                this.keys[i] = kv.Key;
                this.values[i] = kv.Value;
            }
        }
        /// <summary>
        /// 获取与指定的键相关联的值
        /// </summary>
        /// <param name="key">要获取或设置的值的键。</param>
        /// <returns>与指定的键相关联的值</returns>
        public T this[string key]
        {
            get
            {
                if (key == null)
                    throw new ArgumentNullException(key);
                //没有用Linq，Linq性能差
                for (int i = 0; i < this.keys.Length; i++)
                {
                    if (this.keys[i] == key)
                        return this.values[i];
                }
                throw new KeyNotFoundException();
            }
        }

        private readonly string[] keys;
        /// <summary>
        /// 获取键的集合
        /// </summary>
        public string[] Keys
        {
            get { return this.keys; }
        }
        private readonly T[] values;
        /// <summary>
        /// 获取值的集合
        /// </summary>
        public T[] Values
        {
            get { return this.values; }
        }
        /// <summary>
        /// 深度复制
        /// </summary>
        /// <returns></returns>
        ReadonlyOrderedDictionary<T> ICloneable<ReadonlyOrderedDictionary<T>>.Clone()
        {
            KeyValuePair<string, T>[] kvList = new KeyValuePair<string, T>[this.Items.Count];
            Func<T, T> clone = getCloneMethod(this.values.FirstOrDefault(d => d != null));

            for (int i = 0; i < kvList.Length; i++)
            {
                KeyValuePair<string, T> kvCurrent = this.Items[i];
                kvList[i] = new KeyValuePair<string, T>(kvCurrent.Key, clone(kvCurrent.Value));
            }
            return new ReadonlyOrderedDictionary<T>(kvList);
        }
        /// <summary>
        /// 尝试获取对象的深度复制方法，如果失败则获取浅表复制方法
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        private Func<T,T> getCloneMethod(T src)
        {
            if (src is ICloneable<T>)
                return d => ((ICloneable<T>)d).Clone();
            else if (src is ICloneable)
                return d => (T)((ICloneable)d).Clone();
            else
                return d => d;
        }

        object ICloneable.Clone()
        {
            return ((ICloneable<ReadonlyOrderedDictionary<T>>)this).Clone();
        }
    }
    /// <summary>
    /// 表示键或索引可访问的键/值对的只读集合。
    /// </summary>
    public class ReadonlyOrderedDictionary : ReadonlyOrderedDictionary<object>
    {
        internal ReadonlyOrderedDictionary(IList<KeyValuePair<string, object>> list)
            : base(list)
        {
        }
    }
}
